package com.sunday.reactor.dome;

import java.util.concurrent.*;

/**
 * @author mac
 */
public class ThreadPoolExecutorDemo {
	public static void main(String[] args) {
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		// 它的特点在于工作线程数目被限制为 1，操作一个无界的工作队列，所以它保证了所有任务的都是被顺序执行，
		// 最多会有一个任务处于活动状态，并且不允许使用者改动线程池实例，因此可以避免其改变线程数目；
		ExecutorService executorService1 = Executors.newCachedThreadPool();
		// 它是一种用来处理大量短时间工作任务的线程池，具有几个鲜明特点：它会试图缓存线程并重用，当无缓存线程可用时，
		// 就会创建新的工作线程；如果线程闲置的时间超过 60 秒，则被终止并移出缓存；长时间闲置时，这种线程池，
		// 不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列；
		int nThreads = 3;
		ExecutorService executorService2 = Executors.newFixedThreadPool(nThreads);
		// 重用指定数目（nThreads）的线程，其背后使用的是无界的工作队列，任何时候最多有 nThreads 个工作线程是活动的。
		// 这意味着，如果任务数量超过了活动队列数目，将在工作队列中等待空闲线程出现；如果有工作线程退出，
		// 将会有新的工作线程被创建，以补足指定的数目 nThreads；
		ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
		// 创建单线程池，返回 ScheduledExecutorService，可以进行定时或周期性的工作调度；
		int corePoolSize = 3;
		ScheduledExecutorService scheduledExecutorService1 = Executors.newScheduledThreadPool(corePoolSize);
		// 和newSingleThreadScheduledExecutor()类似，创建的是个 ScheduledExecutorService，可以进行定时或周期性的工作调度，
		// 区别在于单一工作线程还是多个工作线程；
		int parallelism = 3;
		ExecutorService executorService3 = Executors.newWorkStealingPool(parallelism);
		// 这是一个经常被人忽略的线程池，Java 8 才加入这个创建方法，其内部会构建ForkJoinPool，利用Work-Stealing算法，
		// 并行地处理任务，不保证处理顺序；
		ThreadPoolExecutor ioExecutor = new ThreadPoolExecutor(10, 20, 200, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));
		//【重要】
		// 是最原始的线程池创建，上面1-3创建方式都是对ThreadPoolExecutor的封装。
		
		//4.7 Executors和ThreaPoolExecutor创建线程池的区别？
		// 《阿里巴巴Java开发手册》中强制线程池不允许使用 Executors 去创建，而是通过 ThreadPoolExecutor 的方式，这样的处理方式让写的同学更加明确线程池的运行规则，规避资源耗尽的风险
		//
		// Executors 各个方法的弊端：
		//
		// newFixedThreadPool 和 newSingleThreadExecutor:
		// 主要问题是堆积的请求处理队列可能会耗费非常大的内存，甚至 OOM。
		// newCachedThreadPool 和 newScheduledThreadPool:
		// 主要问题是线程数最大数是 Integer.MAX_VALUE，可能会创建数量非常多的线程，甚至 OOM。
		// ThreaPoolExecutor创建线程池方式只有一种，就是走它的构造函数，参数自己指定
		
		
	}
}
